package com.leadingsoft.pwxk.service.impl;

import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import com.leadingsoft.plat.model.QLoginLog;
import com.leadingsoft.pwxk.enums.LoginLogEnum;
import com.leadingsoft.pwxk.enums.OperationLogType;
import com.leadingsoft.pwxk.excel.CommonHandleExcel;
import com.leadingsoft.pwxk.excel.ExcelUtil;
import com.leadingsoft.pwxk.model.OperationLog;
import com.leadingsoft.pwxk.model.QOperationLog;
import com.leadingsoft.pwxk.repository.OperationLogRepository;
import com.leadingsoft.pwxk.service.LogService;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.Tuple;
import com.querydsl.jpa.impl.JPAQuery;

@Service
public class LogServiceImpl implements LogService {

	@Autowired
	EntityManager em;

	@Autowired
	OperationLogRepository operationLogRepository;

	QLoginLog qLoginLog = QLoginLog.loginLog;

	QOperationLog qOperationLog = QOperationLog.operationLog;

	@Override
	public Page<OperationLog> getList(Pageable pageable, String search, ZonedDateTime start, ZonedDateTime end) {
		BooleanBuilder booleanBuilder = new BooleanBuilder();
		if (StringUtils.isNoneBlank(search)) {
			booleanBuilder.and(qOperationLog.userName.containsIgnoreCase(search)
					.or(qOperationLog.description.containsIgnoreCase(search))
					.or(qOperationLog.type.containsIgnoreCase(search)));
		}
		if (null != start) {
			booleanBuilder.and(qOperationLog.date.after(start));
		}
		if (null != end) {
			booleanBuilder.and(qOperationLog.date.before(end));
		}
		return operationLogRepository.findAll(booleanBuilder.getValue(),pageable);
	}

	@Override
	public void exportLoginLog(String search, ZonedDateTime start, ZonedDateTime end, HttpServletResponse response,
			String title) {
		List<Map<String, Object>> datas = getData(search, start, end);
		List<String> titleFirst = new ArrayList<>();
		List<String> propertyList = Arrays.asList(new String[] { "no", "user", "ip", "type", "time", "result" });
		List<String> titleList = Arrays.asList(new String[] { "序号", "用户名", "ip", "操作类型", "登录时间", "描述" });
		propertyList = new ArrayList<String>(propertyList);
		titleList = new ArrayList<String>(titleList);
		for (int i = 0; i < propertyList.size(); i++) {
			titleFirst.add(title);
		}
		List<String[]> heads = new ArrayList<>();
		heads.add(titleFirst.toArray(new String[] {}));
		heads.add(titleList.toArray(new String[] {}));
		ExcelUtil.createWorkBook(title, heads, propertyList.toArray(new String[] {}), datas, response,
				new CommonHandleExcel(propertyList.size(), datas.size()), null);
	}

	private List<Map<String, Object>> getData(String search, ZonedDateTime start, ZonedDateTime end) {
		JPAQuery<Tuple> query = new JPAQuery<>(em);
		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
		query.select(qLoginLog.user, qLoginLog.ip, qLoginLog.type, qLoginLog.time, qLoginLog.result);
		query.from(qLoginLog);
		if (StringUtils.isNotBlank(search)) {
			query.where(qLoginLog.user.containsIgnoreCase(search).or(qLoginLog.ip.containsIgnoreCase(search))
					.or(qLoginLog.type.containsIgnoreCase(search)));
		}
		if (null != start) {
			query.where(qLoginLog.time.goe(start));
		}
		if (null != end) {
			query.where(qLoginLog.time.loe(end));
		}
		query.orderBy(qLoginLog.time.asc());
		List<Tuple> fetch = query.fetch();
		List<Map<String, Object>> maps = new ArrayList<Map<String, Object>>();
		Integer i = 0;
		for (Tuple t : fetch) {
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("no", ++i);
			map.put("user", t.get(qLoginLog.user));
			map.put("ip", t.get(qLoginLog.ip));
			map.put("type", LoginLogEnum.getDescByVal(t.get(qLoginLog.type)));
			map.put("time", t.get(qLoginLog.time).format(formatter));
			map.put("result", LoginLogEnum.getDescByVal(t.get(qLoginLog.result)));
			maps.add(map);
		}
		return maps;
	}

	@Override
	public void exportOperationLog(String search, ZonedDateTime start, ZonedDateTime end, HttpServletResponse response,
			String title) {
		List<Map<String, Object>> datas = getOperationLogData(search, start, end);
		List<String> titleFirst = new ArrayList<>();
		List<String> propertyList = Arrays
				.asList(new String[] { "no", "userName", "ip", "type", "date", "description" });
		List<String> titleList = Arrays.asList(new String[] { "序号", "用户名", "ip", "操作类型", "操作时间", "描述" });
		propertyList = new ArrayList<String>(propertyList);
		titleList = new ArrayList<String>(titleList);
		for (int i = 0; i < propertyList.size(); i++) {
			titleFirst.add(title);
		}
		List<String[]> heads = new ArrayList<>();
		heads.add(titleFirst.toArray(new String[] {}));
		heads.add(titleList.toArray(new String[] {}));
		ExcelUtil.createWorkBook(title, heads, propertyList.toArray(new String[] {}), datas, response,
				new CommonHandleExcel(propertyList.size(), datas.size()), null);
	}

	private List<Map<String, Object>> getOperationLogData(String search, ZonedDateTime start, ZonedDateTime end) {
		JPAQuery<Tuple> query = new JPAQuery<>(em);
		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
		query.select(qOperationLog.userName, qOperationLog.ip, qOperationLog.type, qOperationLog.date,
				qOperationLog.description);
		query.from(qOperationLog);
		if (StringUtils.isNotBlank(search)) {
			query.where(qOperationLog.userName.containsIgnoreCase(search)
					.or(qOperationLog.ip.containsIgnoreCase(search)).or(qOperationLog.type.containsIgnoreCase(search)));
		}
		if (null != start) {
			query.where(qOperationLog.date.goe(start));
		}
		if (null != end) {
			query.where(qOperationLog.date.loe(end));
		}
		query.orderBy(qOperationLog.date.asc());
		List<Tuple> fetch = query.fetch();
		List<Map<String, Object>> maps = new ArrayList<Map<String, Object>>();
		Integer i = 0;
		for (Tuple t : fetch) {
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("no", ++i);
			map.put("userName", t.get(qOperationLog.userName));
			map.put("ip", t.get(qOperationLog.ip));
			map.put("type", OperationLogType.getDescByVal(t.get(qOperationLog.type)));
			map.put("date", t.get(qOperationLog.date).format(formatter));
			map.put("description", t.get(qOperationLog.description));
			maps.add(map);
		}
		return maps;
	}
}
